home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / sound / simul100.zip / SIMUL.C < prev    next >
C/C++ Source or Header  |  1995-12-27  |  12KB  |  484 lines

  1. /* █ SIMUL.C ██████████████████████████████████████████████████████████████ */
  2. /*          Copyright 1995 by Ethan Brodsky.  All right reserved.           */
  3.  
  4. #define TRUE  1
  5. #define FALSE 0
  6.  
  7. typedef unsigned char BYTE;
  8.  
  9. int  init_sb(int base_io, int irq, int dma_8, int dma_16, int rate);
  10. void shutdown_sb(void);
  11.  
  12. void set_blocklength(int block_length);
  13.  
  14. void get_buffers(void);
  15. void free_buffers(void);
  16.  
  17. void install_handler_8(void (far *handler)());
  18. void install_handler_16(void (far *handler)());
  19.  
  20. void start_input16(void);
  21. void start_output8(void);
  22.  
  23. void stop_sound(void);
  24.  
  25. volatile long intcount;
  26. volatile long intcount_8;
  27. volatile long intcount_16;
  28.  
  29. volatile int  error = FALSE;
  30.  
  31. int  curblock_8;
  32. int  curblock_16;
  33.  
  34. unsigned char far *blockptr_8[2];
  35. unsigned char far *buf_8;
  36.  
  37. signed short  far *blockptr_16[2];
  38. signed short  far *buf_16;
  39.  
  40. /* ████████████████████████████████████████████████████████████████████████ */
  41.  
  42. #include <alloc.h>
  43. #include <dos.h>
  44. #include <mem.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47.  
  48. #define hi(x) ((x) >> 8)
  49. #define lo(x) ((x) & 0xFF)
  50.  
  51. typedef enum {INT8, INT16, ERROR} INTTYPE;
  52.  
  53. int resetport;
  54. int readport;
  55. int writeport;
  56. int pollport;
  57. int ack8port;
  58. int ack16port;
  59.  
  60. int mixer_addrport;
  61. int mixer_dataport;
  62.  
  63. int sampling_rate;
  64.  
  65. int pic_rotateport;
  66. int pic_maskport;
  67. int irq_startmask;
  68. int irq_stopmask;
  69. int irq_intvector;
  70.  
  71. int dma8_maskport;
  72. int dma8_clrptrport;
  73. int dma8_modeport;
  74. int dma8_addrport;
  75. int dma8_countport;
  76. int dma8_pageport;
  77. int dma8_startmask;
  78. int dma8_stopmask;
  79. int dma8_mode;
  80.  
  81. int dma16_maskport;
  82. int dma16_clrptrport;
  83. int dma16_modeport;
  84. int dma16_addrport;
  85. int dma16_countport;
  86. int dma16_pageport;
  87. int dma16_startmask;
  88. int dma16_stopmask;
  89. int dma16_mode;
  90.  
  91. void far *mem_8 = NULL;
  92. unsigned char far *buf_8 = NULL;
  93. unsigned char far *blockptr_8[2] = {NULL, NULL};
  94. long buffer8_addr;
  95. int  buffer8_page;
  96. int  buffer8_ofs;
  97.  
  98. void far *mem_16 = NULL;
  99. signed short far *buf_16 = NULL;
  100. signed short far *blockptr_16[2] = {NULL, NULL};
  101. long buffer16_addr;
  102. int  buffer16_page;
  103. int  buffer16_ofs;
  104.  
  105. void (far *handler_8)(void)  = NULL;
  106. void (far *handler_16)(void) = NULL;
  107.  
  108. static void (interrupt far *oldintvector)(void) = NULL;
  109. int inthandler_installed = FALSE;
  110.  
  111. unsigned int blocklength  = 0;
  112. unsigned int bufferlength = 0;
  113.  
  114. /* ──────────────────────────────────────────────────────────────────────── */
  115.  
  116. void write_dsp(BYTE value)
  117.   {
  118.     while ((inp(writeport) & 0x80));
  119.     outp(writeport, value);
  120.   }
  121.  
  122. BYTE read_dsp(void)
  123.   {
  124.     while (!(inp(pollport) & 0x80));
  125.     return(inp(readport));
  126.   }
  127.  
  128. void write_mixer(BYTE reg, BYTE value)
  129.   {
  130.     outp(mixer_addrport, reg);
  131.     outp(mixer_dataport, value);
  132.   }
  133.  
  134. BYTE read_mixer(BYTE reg)
  135.   {
  136.     outp(mixer_addrport, reg);
  137.     return inp(mixer_dataport);
  138.   }
  139.  
  140. int reset_dsp(void)
  141.   {
  142.     int i;
  143.  
  144.     outp(resetport, 1);
  145.     delay(1);
  146.     outp(resetport, 0);
  147.  
  148.     i = 100;
  149.     while ((i-- > 0) && (read_dsp() != 0xAA))
  150.       { }
  151.  
  152.     return(i > 0);
  153.   }
  154.  
  155. void set_rate(int rate)
  156.   {
  157.    /* Output rate */
  158.     write_dsp(0x41);
  159.     write_dsp(hi(rate));
  160.     write_dsp(lo(rate));
  161.  
  162.    /* Input rate */
  163.     write_dsp(0x42);
  164.     write_dsp(hi(rate));
  165.     write_dsp(lo(rate));
  166.   }
  167.  
  168. /* ════════════════════════════════════════════════════════════════════════ */
  169.  
  170. void install_inthandler(void);
  171. void uninstall_inthandler(void);
  172. void simul_exitproc(void);
  173.  
  174. int init_sb(int base_io, int irq, int dma_8, int dma_16, int rate)
  175.   {
  176.     static int pageport[8] = {0x87, 0x83, 0x81, 0x82, -1, 0x8B, 0x89, 0x8A};
  177.  
  178.    /* Sound card DSP IO ports */
  179.     resetport = base_io + 0x006;
  180.     readport  = base_io + 0x00A;
  181.     writeport = base_io + 0x00C;
  182.     pollport  = base_io + 0x00E;
  183.     ack8port  = base_io + 0x00E;
  184.     ack16port = base_io + 0x00F;
  185.  
  186.    /* Sound card mixer IO ports */
  187.     mixer_addrport = base_io + 0x004;
  188.     mixer_dataport = base_io + 0x005;
  189.  
  190.    /* Reset DSP */
  191.     if (!reset_dsp())
  192.       return FALSE;
  193.  
  194.    /* Make sure that sound hardware is SB16 */
  195.     write_dsp(0xE1);
  196.     if (read_dsp() < 4)
  197.       return FALSE;
  198.     read_dsp();
  199.  
  200.    /* Calculate interrupt controller ports and parameters */
  201.     if (irq < 8)
  202.       { /* PIC1 */
  203.         irq_intvector  = 0x08 + irq;
  204.         pic_rotateport = 0x20;
  205.         pic_maskport   = 0x21;
  206.       }
  207.     else
  208.       { /* PIC2 */
  209.         irq_intvector  = 0x70 + irq-8;
  210.         pic_rotateport = 0xA0;
  211.         pic_maskport   = 0xA1;
  212.       }
  213.     irq_stopmask  = 1 << (irq % 8);
  214.     irq_startmask = ~irq_stopmask;
  215.  
  216.    /* Calculate DMA controller ports and parameters */
  217.     dma16_maskport   = 0xD4;
  218.     dma16_clrptrport = 0xD8;
  219.     dma16_modeport   = 0xD6;
  220.     dma16_addrport   = 0xC0 + 4*(dma_16-4);
  221.     dma16_countport  = 0xC2 + 4*(dma_16-4);
  222.     dma16_pageport   = pageport[dma_16];
  223.     dma16_stopmask   = 0x04 | (dma_16-4);
  224.     dma16_startmask  = 0x00 | (dma_16-4);
  225.     dma16_mode       = 0x54 | (dma_16-4);  /* single ++ A/I, write to mem   */
  226.  
  227.     dma8_maskport    = 0x0A;
  228.     dma8_clrptrport  = 0x0C;
  229.     dma8_modeport    = 0x0B;
  230.     dma8_addrport    = 0x00 + 2*dma_8;
  231.     dma8_countport   = 0x01 + 2*dma_8;
  232.     dma8_pageport    = pageport[dma_8];
  233.     dma8_stopmask    = 0x04 | dma_8;
  234.     dma8_startmask   = 0x00 | dma_8;
  235.     dma8_mode        = 0x58 | dma_8;       /* single ++ A/I, read from mem  */
  236.  
  237.    /* Sampling rate */
  238.     sampling_rate = rate;
  239.     set_rate(sampling_rate);
  240.  
  241.     install_inthandler();
  242.     atexit(simul_exitproc);
  243.  
  244.     return TRUE;
  245.   }
  246.  
  247. /* ──────────────────────────────────────────────────────────────────────── */
  248.  
  249. void shutdown_sb(void)
  250.   {
  251.     if (inthandler_installed) uninstall_inthandler();
  252.     reset_dsp();
  253.   }
  254.  
  255. /* ════════════════════════════════════════════════════════════════════════ */
  256.  
  257. void set_blocklength(int block_length)
  258.   {
  259.     blocklength = block_length;
  260.     bufferlength = 2*block_length;
  261.   }
  262.  
  263. /* ════════════════════════════════════════════════════════════════════════ */
  264.  
  265. long getlinearaddr(void far *ptr)
  266.   {
  267.     return ((long)FP_SEG(ptr) << 4) + (long)FP_OFF(ptr);
  268.   }
  269.  
  270. void get_buffers(void)
  271.   {
  272.    /* 8-bit */
  273.     buf_8 = mem_8 = malloc(2*bufferlength);
  274.     if (mem_8 == NULL)
  275.       exit(EXIT_FAILURE);
  276.  
  277.     if (((getlinearaddr(mem_8) % 65536) + bufferlength) > 65536)
  278.       buf_8 += 1;
  279.  
  280.     blockptr_8[0] = buf_8;
  281.     blockptr_8[1] = buf_8 + blocklength;
  282.  
  283.     buffer8_addr = getlinearaddr(buf_8);
  284.     buffer8_page = buffer8_addr / 65536;
  285.     buffer8_ofs  = buffer8_addr % 65536;
  286.  
  287.     _fmemset(buf_8, 0x80, bufferlength);
  288.  
  289.    /* 16-bit */
  290.     buf_16 = mem_16 = malloc(4*bufferlength);
  291.     if (mem_16 == NULL)
  292.       exit(EXIT_FAILURE);
  293.  
  294.     if ((((getlinearaddr(mem_16) >> 1) % 65536) + bufferlength) > 65536)
  295.       buf_16 += 1;
  296.  
  297.     blockptr_16[0] = buf_16;
  298.     blockptr_16[1] = buf_16 + blocklength;
  299.  
  300.     buffer16_addr = getlinearaddr(buf_16);
  301.     buffer16_page = buffer16_addr / 65536;
  302.     buffer16_ofs  = (buffer16_addr >> 1) % 65536;
  303.  
  304.     _fmemset(buf_16, 0x00, 2*bufferlength);
  305.  
  306.     curblock_8  = 0;
  307.     curblock_16 = 0;
  308.  
  309.     intcount_8  = 0;
  310.     intcount_16 = 0;
  311.     intcount    = 0;
  312.   }
  313.  
  314. /* ──────────────────────────────────────────────────────────────────────── */
  315.  
  316. void free_buffers(void)
  317.   {
  318. #ifdef __SMALL__ || __MEDIUM__
  319.     free((void *)mem_8);
  320.     free((void *)mem_16);
  321. #else
  322.     farfree(mem_8);
  323.     farfree(mem_16);
  324. #endif
  325.   }
  326.  
  327. /* ════════════════════════════════════════════════════════════════════════ */
  328.  
  329. void install_handler_8(void (far *handler)())
  330.   {
  331.     handler_8 = handler;
  332.   }
  333.  
  334. /* ──────────────────────────────────────────────────────────────────────── */
  335.  
  336. void install_handler_16(void (far *handler)())
  337.   {
  338.     handler_16 = handler;
  339.   }
  340.  
  341. /* ════════════════════════════════════════════════════════════════════════ */
  342.  
  343. void start_input16(void)
  344.   {
  345.     outp(dma16_maskport,   dma16_stopmask);
  346.     outp(dma16_clrptrport, 0x00);
  347.     outp(dma16_modeport,   dma16_mode);
  348.     outp(dma16_addrport,   lo(buffer16_ofs));
  349.     outp(dma16_addrport,   hi(buffer16_ofs));
  350.     outp(dma16_countport,  lo(bufferlength-1));
  351.     outp(dma16_countport,  hi(bufferlength-1));
  352.     outp(dma16_pageport,   buffer16_page);
  353.     outp(dma16_maskport,   dma16_startmask);
  354.  
  355.     write_dsp(0xBE);                    /* 16-bit cmd  - A/D - A/I - FIFO   */
  356.     write_dsp(0x10);                    /* 16-bit mode - signed mono        */
  357.     write_dsp(lo(blocklength-1));
  358.     write_dsp(hi(blocklength-1));
  359.   }
  360.  
  361. /* ──────────────────────────────────────────────────────────────────────── */
  362.  
  363. void start_output8(void)
  364.   {
  365.     outp(dma8_maskport,   dma8_stopmask);
  366.     outp(dma8_clrptrport, 0x00);
  367.     outp(dma8_modeport,   dma8_mode);
  368.     outp(dma8_addrport,   lo(buffer8_ofs));
  369.     outp(dma8_addrport,   hi(buffer8_ofs));
  370.     outp(dma8_countport,  lo(bufferlength-1));
  371.     outp(dma8_countport,  hi(bufferlength-1));
  372.     outp(dma8_pageport,   buffer8_page);
  373.     outp(dma8_maskport,   dma8_startmask);
  374.  
  375.     write_dsp(0x48);                    /* Set DSP block transfer size      */
  376.     write_dsp(lo(blocklength-1));
  377.     write_dsp(hi(blocklength-1));
  378.     write_dsp(0x1C);                    /* 8-bit auto-init DMA mono output  */
  379.   }
  380.  
  381. /* ════════════════════════════════════════════════════════════════════════ */
  382.  
  383. void stop_sound(void)
  384.   {
  385.     write_dsp(0xD0);                      /* Pause 8-bit sound              */
  386.     write_dsp(0xDA);                      /* Exit 8-bit A/I sound           */
  387.     outp(dma8_maskport, dma8_stopmask);   /* Mask DMA channel               */
  388.  
  389.     write_dsp(0xD5);                      /* Pause 16-bit sound             */
  390.     write_dsp(0xD9);                      /* Exit 16-bit A/I sound          */
  391.     outp(dma16_maskport, dma16_stopmask); /* Mask 16-gbit DMA channel       */
  392.   }
  393.  
  394. /* ════════════════════════════════════════════════════════════════════════ */
  395.  
  396. INTTYPE inttype(void)
  397.   {
  398.     BYTE intstatus;
  399.  
  400.    /* Read Interrupt Status Register */
  401.     intstatus = read_mixer(0x82);
  402.  
  403.     if ((intstatus & 0x01) && (intstatus & 0x02))
  404.       return ERROR;
  405.  
  406.     if (intstatus & 0x01)
  407.       return INT8;
  408.  
  409.     if (intstatus & 0x02)
  410.       return INT16;
  411.  
  412.     return ERROR;
  413.   }
  414.  
  415. void toggleblock(int *blocknum)
  416.   {
  417.     *blocknum = !(*blocknum);
  418.   }
  419.  
  420. void interrupt inthandler(void)
  421.   {
  422.     intcount++;
  423.  
  424.     switch(inttype())
  425.       {
  426.        /* 8-bit sound */
  427.         case INT8:
  428.           intcount_8++;
  429.           if (handler_8 != NULL) handler_8();
  430.           toggleblock(&curblock_8);
  431.           inp(ack8port);
  432.           break;
  433.  
  434.        /* 16-bit sound */
  435.         case INT16:
  436.           intcount_16++;
  437.           if (handler_16 != NULL) handler_16();
  438.           toggleblock(&curblock_16);
  439.           inp(ack16port);
  440.           break;
  441.  
  442.        /* Problem */
  443.         case ERROR:
  444.           error = TRUE;
  445.           break;
  446.       }
  447.  
  448.     outp(0xA0, 0x20);                     /* Acknowledge EOI with PIC2      */
  449.     outp(0x20, 0x20);                     /* Acknowledge EOI with PIC1      */
  450.   }
  451.  
  452. void install_inthandler(void)
  453.   {
  454.     disable();
  455.     outp(pic_maskport, (inp(pic_maskport) | irq_stopmask));
  456.  
  457.     oldintvector = _dos_getvect(irq_intvector);
  458.     _dos_setvect(irq_intvector, inthandler);
  459.  
  460.     outp(pic_maskport, (inp(pic_maskport) & irq_startmask));
  461.     enable();
  462.  
  463.     inthandler_installed = TRUE;
  464.   }
  465.  
  466. void uninstall_inthandler(void)
  467.   {
  468.       disable();
  469.       outp(pic_maskport, (inp(pic_maskport) | irq_stopmask));
  470.  
  471.       _dos_setvect(irq_intvector, oldintvector);
  472.  
  473.       enable();
  474.  
  475.       inthandler_installed = FALSE;
  476.   }
  477.  
  478. void simul_exitproc(void)
  479.   {
  480.     stop_sound();
  481.     shutdown_sb();
  482.   }
  483.  
  484. /* ████████████████████████████████████████████████████████████████████████ */